#include "mw.h"
#include<QTextEdit>
#include<QApplication>
#include<QTextEdit>
#include<QTextCodec>
#include<QGridLayout>
#include<QPushButton>
#include<QLineEdit>
#include <QFileDialog>
#include <QFile>
#include <QDir>
#include <QTextStream>
#include <QMessageBox>
#include <QColorDialog>
#include <QColor>
#include <QTextList>
#include <QDebug>
#include <QInputDialog>
#include <QRadioButton>
#include <QSpinBox>
#include <QCheckBox>
#include <QTextDocumentFragment>
#include <QDialog>

#include "./code/tablebase.h"
#include "./code/inibase.h"
#include "./code/sqlopera.h"
//#define ini文件 "词典/新华大字典.ini"
//#define db文件 "词典/新华大字典.db"


MW::MW(QWidget *parent)
    : QMainWindow(parent)
{
   p音频播放 = new QMediaPlayer;
   setWindowTitle(QObject::tr("词典笔记本"));
   resize(800, 600);

   m定时器.start();
   m记忆时间 = m定时器.elapsed();

///竖直分割，增加两个控件，分别为搜索和历史；再水平分割，增加一个控件，显示文本内容。将分割的窗体设为中央窗体。
//{在左分割中添加QGridLayout布局，需要先添加QWidget。
   p左分割 = new QSplitter(Qt::Vertical);

   QGridLayout *p左上网格GLayout= new QGridLayout;
   QWidget *wg1 = new QWidget;
   wg1->setMaximumWidth(300);//对 p左分割 限制宽度没有用, 但可以限制 wg1.
   wg1->setMinimumWidth(50);

   wg1->setLayout(p左上网格GLayout);//布局先添加到QWidget。
   p左分割->addWidget(wg1);//再将QWidget添加到左分割中。

   QLineEdit *p搜索LEdit = new QLineEdit;
   QPushButton *p搜索Btn =new QPushButton;
   p搜索Btn->setText("全搜");

///左上角加入QListView *p单词列表 控件.
    p单词列表 = new QListView;
    p列表模式单词 = new QStringListModel(this);
    p单词列表->setModel(p列表模式单词);

    p左上网格GLayout->addWidget(p搜索LEdit, 0, 0);
    p左上网格GLayout->addWidget(p搜索Btn, 0, 1);
    p左上网格GLayout->addWidget(p单词列表, 1,0,1,2);//起始行,列; 占用的行,列


    //QString str[3]= {"苹果","鸭梨","西瓜"};
//    for(int i=32;i<127;i++)//为 单词列表 生成一组数据显示
//        m单词序列.push_back(QString(i));
//    p列表模式单词->setStringList(m单词序列);//要使用这句才更新列表视图.




///左下角加入QListView *p历史列表 控件.
    p历史列表 = new QListView;
    p列表模式历史= new QStringListModel(this);
    p历史列表->setModel(p列表模式历史);

//    for(int i=128;i<255;i++)//为 历史列表 生成一组数据显示
//        m历史序列.push_back(QString(i));
//    p列表模式历史->setStringList(m历史序列);//要使用这句才更新列表视图.

    QGridLayout *p左下网格GLayout= new QGridLayout;
    QWidget *wg2 = new QWidget(p左分割);// 将p左分割加入到括号中,省略了一行: p左分割->addWidget(wg2);//再将QWidget添加到左分割中。
    p左下网格GLayout->addWidget(p历史列表, 0,0,1,2);//起始行,列; 占用的行,列

    wg2->setLayout(p左下网格GLayout);//布局先添加到QWidget。




   connect(p单词列表, &QListView::clicked, this, &MW::m单词列表点击);
   connect(p历史列表, &QListView::clicked, this, &MW::m历史列表点击);
   connect(p搜索Btn, &QPushButton::clicked, this, &MW::m搜索点击btn);



//}
 //  QString 结果=表中还原html(ini文件,db文件, "字详表", "10");

   p主页分割 = new QSplitter(Qt::Horizontal);
   p主页Edit = new QTextEdit;
   //p主页Edit = new QTextBrowser;
   //p主页Edit->setText(QObject::tr("右窗口"));
 //  p主页Edit->setText(结果);
   p主页分割->addWidget(p左分割);
   p主页分割->addWidget(p主页Edit);

connect(p主页Edit, &QTextEdit::cursorPositionChanged, this, &MW::updateCursorPosition);//跟踪光标处的html元素。

   p主页Edit->append("<img src=\"D:/QtF/dictnote/词典/photo/image.png\" title=\"音频3@D:/QtF/dictnote/词典/audio/温岚 - 夏天的风.mp3\"width=\"50\" height=\"20\" />");

p主页Edit->append("<a href=\"当前词典:表名/ID号\">显示的文本</a>");
   p主页分割->setStretchFactor(0, 4);
   p主页分割->setStretchFactor(1, 9);//左右宽度比为4：9
   p左分割->setStretchFactor(0, 2);//左面窗口上下窗口高度比为2：1
   p左分割->setStretchFactor(1, 1);


   setCentralWidget(p主页分割);//设置为中央窗体

    ///在工具栏上嵌入控件
    //设置字体
    p字体Label =new QLabel(tr("字体:"));
    p字体下拉框 =new QFontComboBox;
    p字体下拉框->setMaximumWidth(130);  // 设置最大宽度为100
   // p字体下拉框->setFixedWidth(100);  // 设置宽度为100
    p字体下拉框->setFontFilters(QFontComboBox::ScalableFonts);  //ScalableFonts表示可缩放的字体。
    p字号Label =new QLabel(tr("字号:"));
    p字号下拉框 =new QComboBox;
    QFontDatabase db;
    foreach(int size,db.standardSizes())
        p字号下拉框->addItem(QString::number(size));
    p粗体Btn =new QToolButton;
    p粗体Btn->setIcon(QIcon("./icon/bold.png"));
    p粗体Btn->setCheckable(true);
    p斜体Btn =new QToolButton;
    p斜体Btn->setIcon(QIcon("./icon/italic.png"));
    p斜体Btn->setCheckable(true);
    p下划线Btn =new QToolButton;
    p下划线Btn->setIcon(QIcon("./icon/underline.png"));
    p下划线Btn->setCheckable(true);
    p颜色Btn =new QToolButton;
    p颜色Btn->setIcon(QIcon("./icon/color.png"));
    p颜色Btn->setCheckable(true);
    //排序
    listLabel =new QLabel(tr("排序"));
    p排序类型框 =new QComboBox;
    p排序类型框->addItem("标准");        //没见有变化, Standard
    p排序类型框->addItem("空心圆点");     //实心圆点, QTextListFormat::ListDisc
    p排序类型框->addItem("空心圆点");     //空心圆点, QTextListFormat::ListCircle
    p排序类型框->addItem("实心方点");    //实心方点. QTextListFormat::ListSquare
    p排序类型框->addItem("数字");    //数字, QTextListFormat::ListDecimal
    p排序类型框->addItem("小写字母"); //小写字母, QTextListFormat::ListLowerAlpha
    p排序类型框->addItem("大写字母"); //大写字母, QTextListFormat::ListUpperAlpha
    p排序类型框->addItem("罗马 i");  //罗马 i, QTextListFormat::ListLowerRoman
    p排序类型框->addItem("罗马 I");  //罗马 I, QTextListFormat::ListUpperRoman

        //排序：左对齐、右对齐、居中和两端对齐
    actGrp =new QActionGroup(this);
    leftAction =new QAction(QIcon("./icon/left.png"),"左对齐",actGrp);
    leftAction->setCheckable(true);
    rightAction =new QAction(QIcon("./icon/right.png"),"右对齐",actGrp);
    rightAction->setCheckable(true);
    centerAction =new QAction(QIcon("./icon/center.png"),"居中",actGrp);
    centerAction->setCheckable(true);
    justifyAction =new QAction(QIcon("./icon/justify.png"),"两端对齐",actGrp);
    justifyAction->setCheckable(true);
    connect(actGrp,SIGNAL(triggered(QAction*)),this,SLOT(ShowAlignment(QAction*)));

    m创建Action();
    m创建Menu();
    m创建ToolBar();

    connect(p字体下拉框,SIGNAL(activated(QString)),this,SLOT(mShowFontComboBox(QString)));
    connect(p字号下拉框,SIGNAL(activated(QString)),this,SLOT(ShowSizeSpinBox(QString)));
    connect(p粗体Btn,SIGNAL(clicked()),this,SLOT(ShowBoldBtn()));
    connect(p斜体Btn,SIGNAL(clicked()),this,SLOT(ShowItalicBtn()));
    connect(p下划线Btn,SIGNAL(clicked()),this,SLOT(ShowUnderlineBtn()));
    connect(p颜色Btn,SIGNAL(clicked()),this,SLOT(ShowColorBtn()));
    connect(p主页Edit,SIGNAL(currentCharFormatChanged(const QTextCharFormat&)),this,SLOT(ShowCurrentFormatChanged(const QTextCharFormat&)));
    //当光标所在处的字符格式发生变化时自动调用此槽函数，显示当前字符的格式。不起作用。是没加const

    connect(p排序类型框,SIGNAL(activated(int)),this,SLOT(ShowList(int)));
    connect(p主页Edit->document(),SIGNAL(undoAvailable(bool)),redoAction,SLOT(setEnabled(bool)));
    connect(p主页Edit->document(),SIGNAL(redoAvailable(bool)),redoAction,SLOT(setEnabled(bool)));
    connect(p主页Edit,SIGNAL(cursorPositionChanged()),this,SLOT(ShowCursorPositionChanged()));






}



MW::~MW()
{

}


void MW::m创建Menu()
{
   //文件菜单
   fileMenu =menuBar()->addMenu(tr("文件"));			//(a)左上角菜单栏显示 文件菜单。
   fileMenu->addAction(openFileAction);				//(b)将openFile动作加入文件菜单中。
   fileMenu->addAction(NewFileAction);
   fileMenu->addAction(fileSave);
   fileMenu->addAction(PrintTextAction);
   fileMenu->addAction(PrintImageAction);
   fileMenu->addSeparator();
   fileMenu->addAction(exitAction);
   //缩放菜单
   zoomMenu =menuBar()->addMenu(tr("编辑"));
   zoomMenu->addAction(copyAction);
   zoomMenu->addAction(cutAction);
   zoomMenu->addAction(pasteAction);
   zoomMenu->addAction(aboutAction);
   zoomMenu->addSeparator();
   zoomMenu->addAction(zoomInAction);
   zoomMenu->addAction(zoomOutAction);

   p书集菜单 =menuBar()->addMenu(tr("书集菜单"));
   p书集菜单->addAction(p打开书集Action);
   p书集菜单->addAction(p新建书集Action);
   p书集菜单->addAction(p增加书本Action);
   p书集菜单->addAction(p选择书本Action);
   p书集菜单->addSeparator();
   p书集菜单->addAction(p删除书本Action);
   p书集菜单->addAction(p删除当前词条Action);
   p书集菜单->addSeparator();
   p书集菜单->addAction(p添加词条Action);
   p书集菜单->addAction(p修改词条Action);
   p书集菜单->addAction(p修改标签Action);
   p书集菜单->addAction(p修改备注Action);

   p插入资源 =menuBar()->addMenu(tr("插入资源"));
   p插入资源->addAction(p插入链接Action);
   p插入资源->addAction(p插入图片Action);
   p插入资源->addAction(p插入音频Action);
//   p插入资源->addAction(p插入视频Action);
//   p插入资源->addAction(p插入文件Action);

   p表格菜单 =menuBar()->addMenu(tr("表格菜单"));
   p表格菜单->addAction(p插入表格Action);
   p表格菜单->addAction(p表格增加一行Action);
   p表格菜单->addAction(p表格增加一列Action);
   p表格菜单->addSeparator();
   p表格菜单->addAction(p表格删除当前行Action);
   p表格菜单->addAction(p表格删除当前列Action);
   p表格菜单->addSeparator();
   p表格菜单->addAction(p表格返回上一步Action);

   p其它菜单 =menuBar()->addMenu(tr("其它菜单"));
   p其它菜单->addAction(p盘符替换Action);

}


void MW::m创建Action()
{
    //“打开”动作
    openFileAction =new QAction(QIcon("./icon/open.png"),tr("打开"),this);//(a)在创建“打开文件”动作的同时，指定了此动作使用的图标、名称及父窗口
    openFileAction->setShortcut(tr("Ctrl+O"));                    //(b)设置此动作的组合键为Ctrl+0。
    openFileAction->setStatusTip(tr("打开一个文件"));               //(c)问：状态栏在哪里？
    connect(openFileAction,SIGNAL(triggered()),this,SLOT(m打开文档文件()));
    //“新建”动作
    NewFileAction =new QAction(QIcon("./icon/new.png"),tr("新建"),this);
    NewFileAction->setShortcut(tr("Ctrl+N"));
    NewFileAction->setStatusTip(tr("新建一个文件"));
    connect(NewFileAction,SIGNAL(triggered()),this,SLOT(ShowNewFile()));
    //“保存”动作
    fileSave = new QAction(QIcon("./icon/new.png"),tr("保存"),this);
    fileSave->setShortcut(tr("Ctrl+S"));
    fileSave->setStatusTip(tr("保存当前文件"));
    connect(fileSave, SIGNAL(triggered()), this, SLOT(m保存当前文件()));
    //“打印文本”动作
    PrintTextAction =new QAction(QIcon("./icon/printText.png"),tr("打印文本"), this);
    PrintTextAction->setStatusTip(tr("打印一个文本"));
    connect(PrintTextAction,SIGNAL(triggered()),this,SLOT(ShowPrintText()));
    //“打印图像”动作
    PrintImageAction =new QAction(QIcon("./icon/printImage.png"),tr("打印图像"), this);
    PrintImageAction->setStatusTip(tr("打印一幅图像"));
    connect(PrintImageAction,SIGNAL(triggered()),this,SLOT(ShowPrintImage()));
    //“退出”动作
    exitAction =new QAction(tr("退出"),this);
    exitAction->setShortcut(tr("Ctrl+Q"));
    exitAction->setStatusTip(tr("退出程序"));
    connect(exitAction,SIGNAL(triggered()),this,SLOT(close()));

    //“复制”动作
    copyAction =new QAction(QIcon("./icon/copy.png"),tr("复制"),this);
    copyAction->setShortcut(tr("Ctrl+C"));
    copyAction->setStatusTip(tr("复制文件"));
    connect(copyAction,SIGNAL(triggered()),p主页Edit,SLOT (copy()));
    //“剪切”动作
    cutAction =new QAction(QIcon("./icon/cut.png"),tr("剪切"),this);
    cutAction->setShortcut(tr("Ctrl+X"));
    cutAction->setStatusTip(tr("剪切文件"));
    connect(cutAction,SIGNAL(triggered()),p主页Edit,SLOT (cut()));
    //“粘贴”动作
    pasteAction =new QAction(QIcon("./icon/paste.png"),tr("粘贴"),this);
    pasteAction->setShortcut(tr("Ctrl+V"));
    pasteAction->setStatusTip(tr("粘贴文件"));
    connect(pasteAction,SIGNAL(triggered()),p主页Edit,SLOT (paste()));
    //“关于”动作
    aboutAction =new QAction(tr("关于"),this);
    connect(aboutAction,SIGNAL(triggered()),this,SLOT (QApplication::aboutQt()));
    //“放大”动作
    zoomInAction =new QAction(QIcon("./icon/zoomin.png"),tr("放大"),this);
    zoomInAction->setStatusTip(tr("放大一张图片"));
    connect(zoomInAction,SIGNAL(triggered()),this,SLOT(ShowZoomIn()));
    //“缩小”动作
    zoomOutAction =new QAction(QIcon("./icon/zoomout.png"),tr("缩小"),this);
    zoomOutAction->setStatusTip(tr("缩小一张图片"));
    connect(zoomOutAction,SIGNAL(triggered()),this,SLOT(ShowZoomOut()));



    //实现撤销和恢复的动作（Action）
    //撤销和恢复
    undoAction =new QAction(QIcon("./icon/undo.png"),"撤销",this);
    undoAction->setShortcut(tr("Ctrl+Z"));
    connect(undoAction,SIGNAL(triggered()),p主页Edit,SLOT (undo()));
    redoAction =new QAction(QIcon("./icon/redo.png"),"重做",this);
    redoAction->setShortcut(tr("Ctrl+Y"));
    connect(redoAction,SIGNAL(triggered()),p主页Edit,SLOT (redo()));

/**词典菜单*******************************************************************************/
    //“打开书集”动作
    p打开书集Action =new QAction(QIcon("./icon/open.png"),tr("打开书集"),this);//(a)在创建“打开文件”动作的同时，指定了此动作使用的图标、名称及父窗口
   // p打开书集Action->setShortcut(tr("Ctrl+O"));                    //(b)设置此动作的组合键为Ctrl+0。
    p打开书集Action->setStatusTip(tr("打开书集文件"));               //(c)问：状态栏在哪里？
    connect(p打开书集Action,SIGNAL(triggered()),this,SLOT(m打开书集文件()));

    p新建书集Action =new QAction(QIcon("./icon/new.png"),tr("新建书集"),this);
   // p新建书集Action->setShortcut(tr("Ctrl+O"));
    p新建书集Action->setStatusTip(tr("新建书集db文件"));
    connect(p新建书集Action,SIGNAL(triggered()),this,SLOT(m新建书集文件()));

    p增加书本Action =new QAction(QIcon("./icon/new.png"),tr("增加书本"),this);
   // p增加书本Action->setShortcut(tr("Ctrl+O"));
    p增加书本Action->setStatusTip(tr("书集中增加词典或笔记"));
    connect(p增加书本Action,SIGNAL(triggered()),this,SLOT(m增加书本()));

    p选择书本Action =new QAction(QIcon("./icon/new.png"),tr("选择书本"),this);
   // p选择书本Action->setShortcut(tr("Ctrl+O"));
    p选择书本Action->setStatusTip(tr("书集中选择一本书"));
    connect(p选择书本Action,SIGNAL(triggered()),this,SLOT(m选择书本()));

    p删除书本Action =new QAction(QIcon("./icon/new.png"),tr("删除书本"),this);
   // p删除书本Action->setShortcut(tr("Ctrl+O"));
    p删除书本Action->setStatusTip(tr("删除词典中一个表"));
    connect(p删除书本Action,SIGNAL(triggered()),this,SLOT(m删除书本()));

    p删除当前词条Action =new QAction(QIcon("./icon/new.png"),tr("删除当前词条"),this);
   // p删除当前词条Action->setShortcut(tr("Ctrl+O"));
    p删除当前词条Action->setStatusTip(tr("删除表中的当前词条"));
    connect(p删除当前词条Action,SIGNAL(triggered()),this,SLOT(m删除词条()));

    p添加词条Action =new QAction(QIcon("./icon/new.png"),tr("添加词条"),this);
   // p添加词条Action->setShortcut(tr("Ctrl+O"));
    p添加词条Action->setStatusTip(tr("添加一个词条"));
    connect(p添加词条Action,SIGNAL(triggered()),this,SLOT(m添加词条()));

    p修改词条Action =new QAction(QIcon("./icon/open.png"),tr("修改当前词条"),this);
   // p修改词条Action->setShortcut(tr("Ctrl+O"));
    p修改词条Action->setStatusTip(tr("修改当前词条"));
    connect(p修改词条Action,SIGNAL(triggered()),this,SLOT(m修改词条()));

    p修改标签Action =new QAction(QIcon("./icon/open.png"),tr("修改标签"),this);
   // p修改标签Action->setShortcut(tr("Ctrl+O"));
    p修改标签Action->setStatusTip(tr("修改当前词条的标签"));
   // connect(p修改标签Action,SIGNAL(triggered()),this,SLOT(m打开文档文件()));

    p修改备注Action =new QAction(QIcon("./icon/open.png"),tr("修改备注"),this);
   // p修改备注Action->setShortcut(tr("Ctrl+O"));
    p修改备注Action->setStatusTip(tr("修改当前词条的备注"));
   // connect(p修改备注Action,SIGNAL(triggered()),this,SLOT(m打开文档文件()));

/**任务*******************************************************************************/
    p任务提交Action =new QAction(QIcon("./icon/task_ok.png"),tr("任务提交"),this);
   // p任务提交Action->setShortcut(tr("Ctrl+O"));
    p任务提交Action->setStatusTip(tr("当前任务提交"));
    connect(p任务提交Action,SIGNAL(triggered()),this,SLOT(m任务提交()));

    p任务取消Action =new QAction(QIcon("./icon/task_cancel.png"),tr("任务取消"),this);
   // p任务取消Action->setShortcut(tr("Ctrl+O"));
    p任务取消Action->setStatusTip(tr("当前任务取消"));
    connect(p任务取消Action,SIGNAL(triggered()),this,SLOT(m任务取消()));

/**p插入资源*******************************************************************************/
    p插入链接Action =new QAction(QIcon("./icon/new.png"),tr("链接"),this);
   // p插入链接Action->setShortcut(tr("Ctrl+O"));
    p插入链接Action->setStatusTip(tr("插入链接"));
    connect(p插入链接Action,SIGNAL(triggered()),this,SLOT(m插入链接()));

    p插入图片Action =new QAction(QIcon("./icon/new.png"),tr("图片"),this);
   // p插入图片Action->setShortcut(tr("Ctrl+O"));
    p插入图片Action->setStatusTip(tr("插入图片"));
    connect(p插入图片Action,SIGNAL(triggered()),this,SLOT(m插入图片()));

    p插入音频Action =new QAction(QIcon("./icon/new.png"),tr("音频"),this);
   // p插入音频Action->setShortcut(tr("Ctrl+O"));
    p插入音频Action->setStatusTip(tr("插入音频"));
    connect(p插入音频Action,SIGNAL(triggered()),this,SLOT(m插入音频()));

//    p插入视频Action =new QAction(QIcon("./icon/new.png"),tr("视频"),this);
//   // p插入视频Action->setShortcut(tr("Ctrl+O"));
//    p插入视频Action->setStatusTip(tr("插入视频"));
//    //connect(p插入视频Action,SIGNAL(triggered()),this,SLOT(m任务取消()));

//    p插入文件Action =new QAction(QIcon("./icon/new.png"),tr("文件"),this);
//   // p插入文件Action->setShortcut(tr("Ctrl+O"));
//    p插入文件Action->setStatusTip(tr("插入文件"));
//    //connect(p插入文件Action,SIGNAL(triggered()),this,SLOT(m任务取消()));

/**p表格菜单*******************************************************************************/
    p插入表格Action =new QAction(QIcon("./icon/new.png"),tr("插入表格"),this);
    p插入表格Action->setStatusTip(tr("插入表格"));
    connect(p插入表格Action,SIGNAL(triggered()),this,SLOT(m插入表格()));

    p表格增加一行Action =new QAction(QIcon("./icon/new.png"),tr("增加一行"),this);
    p表格增加一行Action->setStatusTip(tr("增加一行"));
    connect(p表格增加一行Action,SIGNAL(triggered()),this,SLOT(m表格增加一行()));

    p表格增加一列Action =new QAction(QIcon("./icon/new.png"),tr("增加一列"),this);
    p表格增加一列Action->setStatusTip(tr("增加一列"));
    connect(p表格增加一列Action,SIGNAL(triggered()),this,SLOT(m表格增加一列()));

    p表格删除当前行Action =new QAction(QIcon("./icon/new.png"),tr("删除当前行"),this);
    p表格删除当前行Action->setStatusTip(tr("删除当前行"));
    connect(p表格删除当前行Action,SIGNAL(triggered()),this,SLOT(m表格删除当前行()));

    p表格删除当前列Action =new QAction(QIcon("./icon/new.png"),tr("删除当前列"),this);
    p表格删除当前列Action->setStatusTip(tr("删除当前列"));
    connect(p表格删除当前列Action,SIGNAL(triggered()),this,SLOT(m表格删除当前列()));

    p表格返回上一步Action =new QAction(QIcon("./icon/new.png"),tr("返回上一步"),this);
    p表格返回上一步Action->setStatusTip(tr("表格操作返回上一步"));
    connect(p表格返回上一步Action,SIGNAL(triggered()),this,SLOT(m表格返回上一步()));


/**p其它菜单*******************************************************************************/
    p盘符替换Action =new QAction(QIcon("./icon/new.png"),tr("盘符替换"),this);
   // p盘符替换Action->setShortcut(tr("Ctrl+O"));
    p盘符替换Action->setStatusTip(tr("盘符替换"));
    connect(p盘符替换Action,SIGNAL(triggered()),this,SLOT(m盘符替换()));








}





void MW::m创建ToolBar()
{

    //字体工具条
    fontToolBar =addToolBar("Font");
    fontToolBar->addWidget(p字体Label);
    fontToolBar->addWidget(p字体下拉框);
    fontToolBar->addWidget(p字号Label);
    fontToolBar->addWidget(p字号下拉框);
    fontToolBar->addSeparator();
    fontToolBar->addWidget(p粗体Btn);
    fontToolBar->addWidget(p斜体Btn);
    fontToolBar->addWidget(p下划线Btn);
    fontToolBar->addSeparator();
    fontToolBar->addWidget(p颜色Btn);
    //排序工具条
    listToolBar =addToolBar("list");
    listToolBar->addActions(actGrp->actions());
    listToolBar->addSeparator();
    listToolBar->addWidget(listLabel);
    listToolBar->addWidget(p排序类型框);

//    //文件工具条
//    fileTool =addToolBar("File");					//(a)新增了工具条，但File这词不会显示在界面上。
//    fileTool->addAction(openFileAction);			//(b)将openFile动作加入工具条fileTool中。
//    fileTool->addAction(NewFileAction);
//    fileTool->addAction(PrintTextAction);
//    fileTool->addAction(PrintImageAction);
    //编辑工具条
    zoomTool =addToolBar("Edit");
//    zoomTool->addAction(copyAction);
//    zoomTool->addAction(cutAction);
    zoomTool->addAction(pasteAction);
//    zoomTool->addSeparator();
//    zoomTool->addAction(zoomInAction);   //放大
//    zoomTool->addAction(zoomOutAction);  //缩小

    //撤销和重做工具条
    doToolBar =addToolBar("doEdit");
    doToolBar->addAction(undoAction);
    doToolBar->addAction(redoAction);

    //任务提交和取消工具条
    taskToolBar=addToolBar("task");
    taskToolBar->addAction(p任务提交Action);
    taskToolBar->addAction(p任务取消Action);


}


void MW::m打开文档文件()
{
    QString filename = QFileDialog::getOpenFileName(this, tr("打开文件"),
                                                    QDir::currentPath(),
                                                    tr("富文本(*.rtf);;纯文本(*.txt)"));
    QString Path(filename);
    setWindowTitle(Path);


    QFile file(filename);
    if(file.open(QFile::ReadWrite))
    {
        p主页Edit->clear();
        QTextStream stream(&file);
        if(!stream.atEnd())
        {
            p主页Edit->setText(stream.readAll());
        }
    }

}

void MW::m保存当前文件()
{
    QFileDialog dialog(this,"保存文件","C:\\Users\\Administrator\\Desktop"
                       ,tr("富文本(*.rtf);;纯文本(*.txt)"));

    dialog.setAcceptMode(QFileDialog::AcceptSave);

    QString fileName;
    QString filterMod;

    if(dialog.exec())
    {
        fileName  = dialog.selectedFiles()[0];
        filterMod = dialog.selectedNameFilter();
    }

    QFile file(fileName);

    if(file.open(QFile::WriteOnly |QFile::Truncate))
    {
        QTextStream stream(&file);
        if("富文本(*.rtf)" == filterMod)
            stream<<p主页Edit->toHtml().toUtf8();

        if("纯文本(*.txt)" == filterMod)
            {
                 QMessageBox::StandardButton button =
                     QMessageBox::warning(this, tr("提示"),
                         QString(tr("保存为纯文本格式，颜色、字体等属性会丢失。\n确定要这样做么?")),
                                          QMessageBox::Yes|QMessageBox::No,QMessageBox::No);

                 if(button == QMessageBox::Yes)
                 {
                     stream<<p主页Edit->toPlainText().toUtf8();
                 }
                 else
                 {
                     ;
                 }

            }

    }


    file.close();
}


void MW::ShowCurrentFormatChanged(const QTextCharFormat &fmt)//当光标所在处的字符格式发生变化时自动调用此槽函数，显示当前字符的格式。但好像不起作用。
{
    p字体下拉框->setCurrentIndex(p字体下拉框->findText(fmt.fontFamily()));
    p字号下拉框->setCurrentIndex(p字号下拉框->findText(QString::number(fmt.fontPointSize())));
    p粗体Btn->setChecked(fmt.font().bold());
    p斜体Btn->setChecked(fmt.fontItalic());
    p下划线Btn->setChecked(fmt.fontUnderline());
    qDebug()<<"ShowCurrentFormatChanged"<<"显示当前格式改变";
}


void MW::mShowFontComboBox(QString comboStr)	//设置字体
{
    QFont font;//要加入这几才能解决font-family有两个字体并列且改不了第一个的问题。
    font.setFamily("");
    font.setBold(p主页Edit->currentFont().bold());//获取原来的加粗、斜体、字号，下划线再设置进font中。
    font.setItalic(p主页Edit->currentFont().italic());
    font.setPointSize(p主页Edit->currentFont().pointSize());
    font.setUnderline(p主页Edit->currentFont().underline());
    p主页Edit->setCurrentFont(font);
    //qDebug()<<"字体格式"<<p主页Edit->currentFont();


    QTextCharFormat fmt;		 //创建一个QTextCharFormat对象
    fmt.setFontFamily(comboStr); //选择的字体名称设置给QTextCharFormat对象
    mergeFormat(fmt);     		 //将新的格式应用到光标选区内的字符
    p主页Edit->mergeCurrentCharFormat(fmt);
//    qDebug()<<"设置字体"<<comboStr;
//    qDebug()<<"字体格式"<<fmt;
}

//
void MW::mergeFormat(QTextCharFormat format)//用来获取光标所选区域，设置各种格式。
{
    QTextCursor cursor =p主页Edit->textCursor();
    //获得编辑框中的光标
    if(!cursor.hasSelection())							//(a)若光标没有高亮选区，则将光标所在处的词作为选区，由前后空格或",""."等标点符号区分词。
        cursor.select(QTextCursor::WordUnderCursor);
    cursor.mergeCharFormat(format);						//(b)调用 QTextCursor的mergeCharFormat() 函数将参数format 所表示的格式应用到光标所在处的字符上。

    p主页Edit->mergeCurrentCharFormat(format);	//(c)调用 QTextEdit的merge CurrentChar Format() 函数将格式应用到选区内的所有字符上。



}

void MW::ShowSizeSpinBox(QString spinValue)	//设置字号
{
   QTextCharFormat fmt;
   fmt.setFontPointSize(spinValue.toFloat());
   p主页Edit->mergeCurrentCharFormat(fmt);
   //qDebug()<<"邪不压正"<<fmt;

   //在光标处插入文本
//   QTextCharFormat format;
//   format.setFontWeight(QFont::Bold);
//   format.setForeground(QBrush(Qt::red));
//   QTextCursor cursor(p主页Edit->textCursor());
//    cursor.insertHtml("<b>Hello, world!</b>");
//   cursor.insertText("world!",format);
}


void MW::ShowBoldBtn()                        //设置文字显示加粗
{
    QTextCharFormat fmt;
    fmt.setFontWeight(p粗体Btn->isChecked()?QFont::Bold:QFont::Normal);
   p主页Edit->mergeCurrentCharFormat(fmt);
}

void MW::ShowItalicBtn()                      //设置文字显示斜体
{
    QTextCharFormat fmt;
    fmt.setFontItalic(p斜体Btn->isChecked());
    p主页Edit->mergeCurrentCharFormat(fmt);
}

void MW::ShowUnderlineBtn()                   //设置文字加下画线
{
    QTextCharFormat fmt;
    fmt.setFontUnderline(p下划线Btn->isChecked());
    p主页Edit->mergeCurrentCharFormat(fmt);
}

void MW::ShowColorBtn()						//设置文字颜色
{
    QColor color=QColorDialog::getColor(Qt::red,this);	//(a)使用了标准颜色对话框的方式，当单击“颜色”按钮时，在弹出的标准颜色对话框中选择颜色。
    if(color.isValid())
    {
        QTextCharFormat fmt;
            fmt.setForeground(color);
            p主页Edit->mergeCurrentCharFormat(fmt);
    }
}

void MW::ShowAlignment(QAction *act)  //行的对齐方式
{
    if(act==leftAction)
        p主页Edit->setAlignment(Qt::AlignLeft);
    if(act==rightAction)
        p主页Edit->setAlignment(Qt::AlignRight);
    if(act==centerAction)
        p主页Edit->setAlignment(Qt::AlignCenter);
    if(act==justifyAction)
        p主页Edit->setAlignment(Qt::AlignJustify);
}


void MW::ShowCursorPositionChanged()//响应文本中光标位置处发生改变
{
    if(p主页Edit->alignment()==Qt::AlignLeft)
        leftAction->setChecked(true);
    if(p主页Edit->alignment()==Qt::AlignRight)
        rightAction->setChecked(true);
    if(p主页Edit->alignment()==Qt::AlignCenter)
        centerAction->setChecked(true);
    if(p主页Edit->alignment()==Qt::AlignJustify)
        justifyAction->setChecked(true);
    qDebug()<<"ShowCursorPositionChanged"<<"显示光标位置改变";


}

void MW::ShowList(int index)//文本列表项
{
    //获得编辑框的QTextCursor对象指针
    QTextCursor cursor=p主页Edit->textCursor();
    if(index!=0)
    {
        QTextListFormat::Style style=QTextListFormat::ListDisc;//(a)从下拉列表框中选择确定 QTextListFormat style 属性值。
        switch(index)                					//设置style属性值
        {
            default:
            case 1:
                style=QTextListFormat::ListDisc; break;
            case 2:
                style=QTextListFormat::ListCircle; break;
            case 3:
                style=QTextListFormat::ListSquare; break;
            case 4:
                style=QTextListFormat::ListDecimal; break;
            case 5:
                style=QTextListFormat::ListLowerAlpha; break;
            case 6:
                style=QTextListFormat::ListUpperAlpha; break;
            case 7:
                style=QTextListFormat::ListLowerRoman; break;
            case 8:
                style=QTextListFormat::ListUpperRoman; break;
        }
        /* 设置缩进值 */								//(b)此代码段完成 QTextListFormat 的另一个属性 indent (即缩进值）的设定，并将设置的格式应用到光标所在的文本处。
        cursor.beginEditBlock();
        QTextBlockFormat blockFmt=cursor.blockFormat();
        QTextListFormat listFmt;
        if(cursor.currentList())
        {
            listFmt= cursor.currentList()->format();
        }
        else
        {
            listFmt.setIndent(blockFmt.indent()+1);
            blockFmt.setIndent(0);
            cursor.setBlockFormat(blockFmt);
        }
        listFmt.setStyle(style);
        cursor.createList(listFmt);
        cursor.endEditBlock();
    }
    else
    {
        QTextBlockFormat bfmt;
        bfmt.setObjectIndex(-1);
        cursor.mergeBlockFormat(bfmt);
    }
}




bool  MW::m打开书集文件()
{
    QString filename = QFileDialog::getOpenFileName(this, tr("打开书集文件"),
                                                    QDir::currentPath(),
                                                    tr("数据库(*.db);"));
    if(filename.isEmpty())
    {   return false;}

    m当前打开词条="";//目前没有打开词条,应清空
    m单词序列.clear();
    p列表模式单词->setStringList(m单词序列);//要使用这句才更新列表视图.
    m历史序列.clear();
    p列表模式历史->setStringList(m历史序列);//打开任何db文件都清空历史列表.

    QString Path(filename);
    setWindowTitle(Path);
    m词典文件=filename;//更新m词典文件的路径

qDebug() <<"数据库路径 "<<m词典文件;

    QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
    QSqlDatabase db =QSqlDatabase::addDatabase("QSQLITE");//以“QSQLITE”为数据库类型，在本进程地址空间内创建一个SQLite数据库。

    db.setDatabaseName(Path);              //设置数据库名
    db.open();
     if (!db.open()) {
        qDebug() << "打开数据库失败";
    }

    QStringList 表的名称列表;
    QSqlQuery query(db);


    query.exec("SELECT name FROM sqlite_master WHERE type='table'");//打印出数据库文件中表的名称.
    while (query.next()) {
        QString 表名 = query.value(0).toString();
        qDebug() << 表名;
        if(表名 != "sqlite_sequence")//除了这个表,其它表都加入选项中.
        {   表的名称列表.push_back(表名);}
    }

    bool ok;
    m表名= QInputDialog::getItem(this,tr("选择书本"), tr("请选择书本："),表的名称列表,0,false,&ok);

    int index =m词典文件.lastIndexOf("/");
        m词典路径=m词典文件.mid(0,index);//得到词典的路径
        mINI文件=m词典路径+"/tableSet/"+m表名+".ini";//更新ini的路径
    m词条模板文件=m词典路径+"/tableSet/"+m表名+".rtf";//更新模板rtf的路径
qDebug() <<"数据库路径fqew "<<m词典文件<<mINI文件<<m词条模板文件;

   setWindowTitle(m词典文件+"  "+m表名);


    db.close();                             		//关闭连接
    m更新词典序列();
    return true;
}


void MW::m新建书集文件()
{
// 预设文件名
    QString fileName = "书集文件.db";

    // 创建并显示文件对话框
    QString filePath = QFileDialog::getSaveFileName(nullptr,
                       "保存文件",
                       QDir::currentPath() + "/" + fileName,
                       "数据库文件 (*.db)");

    if (filePath.isEmpty())
    {
        QMessageBox::information(nullptr, "文件未保存", "未保存文件！");
    }
    else
    {
        m当前打开词条="";//目前没有打开词条,应清空
        m单词序列.clear();
        p列表模式单词->setStringList(m单词序列);//要使用这句才更新列表视图.
        m历史序列.clear();
        p列表模式历史->setStringList(m历史序列);//要使用这句才更新列表视图.
        p主页Edit->setText("");



        m词典文件=filePath;//更新m词典文件的路径
        int index =m词典文件.lastIndexOf("/");
        m词典路径=m词典文件.mid(0,index);//得到词典的路径
        qDebug() <<"词典文件: "<<m词典文件;


        //保存文件到硬盘
        QFile file(filePath);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QMessageBox::critical(nullptr, "文件保存失败", "无法打开文件进行写入！");
            // return -1;
        }
        else
        {
            setWindowTitle(m词典文件+"  "+m表名);
            文件复制到另一位置("./模板/audioT.png", m词典路径+"/photo/audioT.png");//默认的音频图标复制到db的photo文件夹.
        }
        file.close();
    }

}


void MW::m增加书本()
{

    // 在你的对话框类的构造函数中
    QWidget *dialog = new QWidget;
    QVBoxLayout *layout = new QVBoxLayout(dialog);

    QLineEdit *tableName = new  QLineEdit("表名", dialog);
    QRadioButton *radioButtonDict = new QRadioButton("新建词典表", dialog);
    QRadioButton *radioButtonNote = new QRadioButton("新建笔记本", dialog);
    QPushButton *pushButtonOK = new QPushButton("确定新建", dialog);
    QPushButton *pushButtonCancel = new QPushButton("取消", dialog);
    radioButtonDict->setChecked(true);

    // 将控件添加到布局中
    layout->addWidget(tableName);
    layout->addWidget(radioButtonDict);
    layout->addWidget(radioButtonNote);
    layout->addWidget(pushButtonOK);
    layout->addWidget(pushButtonCancel);
    dialog->show();

    int index= -2;
    index=m词典文件.indexOf(".db");
    if(index != -1)
    {

        m当前打开词条="";//目前没有打开词条,应清空

        connect(pushButtonOK, &QPushButton::clicked, [=]() {

        //检查是否打开了db文件，检查要新建的是词典还是笔记，复制对应的模板到db的文件夹，改名为表名一致，新建表名一致的ini文件。
        //编辑rtf模板文件，完成后提交任务，完成表的建立，ini文件的编辑。


        m表名=tableName->text();//获得表名   //问题: 若取消新建这个表, m表名无法回到之前的表名

        if(radioButtonDict->isChecked())
        {
            m复制模板文件("./模板/词典模板.rtf");
            m任务名="新建词典表";
        }
        if(radioButtonNote->isChecked())
        {
            m复制模板文件("./模板/笔记模板.rtf");
            m任务名="新建笔记本";
        }

        m单词序列.clear();//清空单词列表显示
        p列表模式单词->setStringList(m单词序列);//要使用这句才更新列表视图.

        dialog->deleteLater();
        delete dialog;
        //后面要到 任务提交 函数中继续完成.


        });
    }
    else//如果db文件没有打开过
    {
        dialog->hide();
        QMessageBox::information(nullptr, "提示", "需要先打开db文件！");
        dialog->deleteLater();
        delete dialog;


    }
    //取消按键，关闭窗口。
    connect(pushButtonCancel, &QPushButton::clicked, [=]() {
        //qDebug() << "pushButtonCancel!";
        dialog->deleteLater();
        delete dialog;
    });



}

//"词典模板.rtf"
//"笔记模板.rtf"
//ini模板.ini
//p主页Edit 会打开显示复制后的rtf模板，同时也复制ini模板
void MW::m复制模板文件(QString 模板名)
{
   int index=-2;
            /********打开模板文件***************************开始**/
            QFile file(模板名);
            if(file.open(QFile::ReadWrite))
            {
                p主页Edit->clear();
                QTextStream stream(&file);
                if(!stream.atEnd())
                {
                 p主页Edit->setText(stream.readAll());
                }
            }
            file.close();
           /********打开模板文件***************************结束**/
           /********模板文件复制到新的路径***************************开始**/
            index=m词典文件.lastIndexOf("/");

            QString  表FileName=m词典文件.mid(0,index+1);//新的路径是db文件所在的目录
            表FileName+="tableSet/"+m表名;

            mINI文件=表FileName+".ini";//更新ini文件的路径
            m词条模板文件=表FileName+".rtf";//更新rtf模板文件的路径

            文件复制到另一位置(模板名, m词条模板文件);
            文件复制到另一位置("./模板/ini模板.ini", mINI文件);

            qDebug() << "m词典文件55"<<m词典文件<<index;
            qDebug() << "表FileName"<<表FileName;
//            QFile file2(rtfFileName);

//            if(file2.open(QFile::WriteOnly |QFile::Truncate))
//            {
//                QTextStream stream(&file2);
//                stream<<p主页Edit->toHtml().toUtf8();
//            }
//            file2.close();
            /********模板文件复制到新的路径***************************结束**/
            /********从新的模板文件打开***************************开始**/
            QFile file3(m词条模板文件);
            if(file3.open(QFile::ReadWrite))
            {
                p主页Edit->clear();
                QTextStream stream(&file3);
                if(!stream.atEnd())
                {
                 p主页Edit->setText(stream.readAll());
                }
            }
            file3.close();
            /********从新的模板文件打开***************************结束**/

/********模板ini文件复制到db所在文件夹***************************开始**/
//    QFile file4("./模板/ini模板.ini");
//    QString ini内容;
//    if(file4.open(QFile::ReadOnly))
//    {
//        QTextStream stream(&file4);
//        if(!stream.atEnd())
//        {
//            ini内容=stream.readAll();
//        }
//    }
//    file4.close();
//qDebug() << "ini内容"<<ini内容;
//    QFile file5(mINI文件);
//    if(file5.open(QFile::WriteOnly |QFile::Truncate))
//    {
//        QTextStream stream(&file5);
//        stream<<ini内容;
//    }
//    file5.close();
/********模板ini文件复制到db所在文件夹***************************结束**/

}


void MW::m任务提交()
{
    if(m任务名=="新建词典表")
    {//保存模板文件, 从模板中生成ini文件, 从ini文件中得到段名再建表.

        QFile file(m词条模板文件);
        if(file.open(QFile::WriteOnly |QFile::Truncate))//保存模板文件,
        {
            QTextStream stream(&file);
            stream<<p主页Edit->toHtml().toUtf8();
        }
        file.close();

        QString text = p主页Edit->toHtml().toUtf8();

        规整化词典模板(text, mINI文件);//从模板中生成ini文件

        创建新表(mINI文件, m词典文件, m表名);//从ini文件中得到段名再建表.
        //qDebug()<<"mINI文件  ttt"<<mINI文件;
        m任务名="";//清空任务
        setWindowTitle(m词典文件+"  "+m表名);
        //问题: 实际这里没法知道词典表是否建立成功.
        p主页Edit->setText("新建词典表成功");
    }

    if(m任务名=="新建笔记本")
    {
        QFile file(m词条模板文件);
        if(file.open(QFile::WriteOnly |QFile::Truncate))//保存模板文件,
        {
            QTextStream stream(&file);
            stream<<p主页Edit->toHtml().toUtf8();
        }
        file.close();

        规整化笔记模板(mINI文件);//从模板中生成ini文件
        //qDebug()<<"到这里了11";
        创建新表(mINI文件, m词典文件, m表名);//从ini文件中得到段名再建表.
       //qDebug()<<"到这里了22";
        m任务名="";//清空任务
        setWindowTitle(m词典文件+"  "+m表名);
        //问题: 实际这里没法知道笔记本是否建立成功.
        p主页Edit->setText("新建笔记本成功");
    }

    if(m任务名=="添加词条")
    {

    // 获取所有文本
        QString 文本 = p主页Edit->toHtml().toUtf8();//QString转QStringList

        表添加词条数据(mINI文件, m词典文件, m表名, 文本 );
         qDebug()<<"七七七";
        m任务名="";//清空任务
        m更新词典序列();
        p主页Edit->setText(m表名+" 添加词条成功");
    }

    if(m任务名=="修改词典词条")
    {
      if(m当前打开词条.length()>2)
      {
        //QString SQL语句="DELETE FROM "; //  表名  WHERE ID = id;  //id 数字不加单引号

        int index1=m当前打开词条.lastIndexOf(" ");
        int index2=m当前打开词条.lastIndexOf("\t");//ID显示在每一列的最后和tab和空格之间

        QString ID=m当前打开词条.mid(index1+1,index2-index1-1);
        QString 表名=m当前打开词条.mid(index2+1,m当前打开词条.length()-index2-1);
        QString ini文件=m词典路径+"/tableSet/"+表名+".ini";

        QString text =p主页Edit->toHtml().toUtf8();;
        QString 返回信息 = 修改db词典词条(ini文件, m词典文件, 表名, ID, text);

        QString 结果=表中还原html(ini文件,m词典文件, 表名, ID, &ID);//ID后面不用了, 随意用&ID代替列表词

        p主页Edit->setText(结果);
        m任务名="";//清空任务

      }
    }

    if(m任务名=="修改笔记词条")
    {
        int index1=m当前打开词条.lastIndexOf(" ");
        int index2=m当前打开词条.lastIndexOf("\t");//ID显示在每一列的最后和tab和空格之间

        QString ID=m当前打开词条.mid(index1+1,index2-index1-1);
        QString 表名=m当前打开词条.mid(index2+1,m当前打开词条.length()-index2-1);
        QString ini文件=m词典路径+"/tableSet/"+表名+".ini";

        QString text =p主页Edit->toHtml().toUtf8();;

        QString 返回信息=修改db笔记词条(ini文件, m词典文件, 表名, ID, text);

         p主页Edit->setText("修改成功");
        m任务名="";//清空任务
    }

}


void MW::m任务取消()
{

///问题: 取消任务后, ini地址和模板地址没有得到回退.

    if(m任务名=="新建词典表" || m任务名=="新建笔记本")
    {
        QFile file(m词条模板文件);//删除已保存的文件
        if(file.exists()) file.remove();
        QFile file1(mINI文件);
        if(file1.exists()) file1.remove();

        QMessageBox::information(nullptr, "提示", m任务名+" 任务已取消");
        m任务名="";
    }
    m任务名="";
}


void MW::m添加词条()
{
    m任务名="添加词条";
            QFile file(m词条模板文件);
            if(file.open(QFile::ReadWrite))
            {
                p主页Edit->clear();
                QTextStream stream(&file);
                if(!stream.atEnd())
                {
                 p主页Edit->setText(stream.readAll());
                }
            }
            file.close();
}


void MW::m更新词典序列()
{
    QString Path(m词典文件);

    QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
    QSqlDatabase db =QSqlDatabase::addDatabase("QSQLITE");//以“QSQLITE”为数据库类型，在本进程地址空间内创建一个SQLite数据库。

    db.setDatabaseName(Path);              //设置数据库名
    db.open();
     if (!db.open()) {
        qDebug() << "打开数据库失败";
    }

    QSqlQuery query(db);


 //   mINI文件=m词典文件.mid(0,index+1)+m表名+".ini";//更新ini的路径
 //   m词条模板文件=m词典文件.mid(0,index+1)+m表名+".rtf";//更新模板rtf的路径
qDebug() <<"数据库路径gdg "<<m词典文件<<mINI文件<<m词条模板文件;


    QStringList 要读的列=ini读尖括号格式(mINI文件, "<->");
    QString SQL语句="SELECT ";

    for(int i=0; i<要读的列.length(); i++)
    {
        SQL语句+=要读的列[i]+",";
    }
    SQL语句+="ID FROM "+m表名;
qDebug() <<"SQL语句 "<<SQL语句;



        m单词序列.clear();
        p列表模式单词->setStringList(m单词序列);//要使用这句才更新列表视图.

        query.exec(SQL语句);//将表中所有项显示到 p列表模式单词 中.

        while (query.next())
        {
            QString rowData = "";
            QSqlRecord record = query.record();
            for (int i = 0; i < record.count(); ++i)
            {

                if (i > 0) {//后面加4个格开
                    rowData += "    ";
                }
                rowData += 去除尖括号并限制长度(record.value(i).toString());
            }

            m单词序列.push_back(rowData);
       // qDebug() << rowData;
        }

        p列表模式单词->setStringList(m单词序列);//要使用这句才更新列表视图.

    db.close();                             		//关闭连接

}

void MW::m更新历史序列(QString 词条ID表名)
{
//    if(m历史序列.length()>0)
//    {
//        if(m历史序列[0] != 词条ID表名)//为了防止同样的地址重复插入最前面.
//        {
//            m历史序列.prepend(词条ID表名);
//            p列表模式历史->setStringList(m历史序列);//要使用这句才更新列表视图.
//        }
//    }
//    else//这是第一次插入
//    {
//        m历史序列.prepend(词条ID表名);
//        p列表模式历史->setStringList(m历史序列);//要使用这句才更新列表视图.
//    }



    for(int i=0; i<m历史序列.length();i++)
    {
        if(词条ID表名 == m历史序列[i])//在开始或中间有相同的
        {
            m历史序列.removeAt(i);  //删除相同的元素
            m历史序列.prepend(词条ID表名);//相同的元素加到最前面
            p列表模式历史->setStringList(m历史序列);//要使用这句才更新列表视图.
            break;
        }
        if( m历史序列.length()<= i+1)//找到最后也没有相同的.
        {
            m历史序列.prepend(词条ID表名);//没有出现过的元素到最前面
            p列表模式历史->setStringList(m历史序列);//要使用这句才更新列表视图.
            break;
        }
    }

    if(m历史序列.length() == 0)//一开始历史序列没有元素, 要新增一个
    {
        m历史序列.append(词条ID表名);//相同的元素加到最前面
        p列表模式历史->setStringList(m历史序列);//要使用这句才更新列表视图.
    }

}

void MW::m搜索点击btn()
{
    p主页Edit->setText("m搜索点击btn");

}


void MW::m单词列表点击()
{

    // 获取选中的项的索引列表
    QModelIndexList selectedIndexes = p单词列表->selectionModel()->selectedIndexes();

    // 遍历选中项的索引列表
    QString text;
    foreach (const QModelIndex &index, selectedIndexes) {
    // 获取选中项的文本内容
        text = p单词列表->model()->data(index, Qt::DisplayRole).toString();
    // 处理文本内容
    }
    int index=text.lastIndexOf(" ");//ID显示在每一列的最后
    QString ID=text.mid(index+1,text.length()-index-1);

    m当前打开词条=text+"\t"+m表名;//更新这值

    QString 结果=表中还原html(mINI文件,m词典文件, m表名, ID, &ID);//ID后面不用了, 随意用&ID代替列表词

    p主页Edit->setText(结果);
    m更新历史序列(text+"\t"+m表名);


}

//问题: 要设置表名不能有空格啊

void MW::m历史列表点击()
{
   qDebug()<<"m历史列表点击gg";
   // 获取选中的项的索引列表
    QModelIndexList selectedIndexes = p历史列表->selectionModel()->selectedIndexes();

    // 遍历选中项的索引列表
    QString text;
    foreach (const QModelIndex &index, selectedIndexes) {
    // 获取选中项的文本内容
        text = p历史列表->model()->data(index, Qt::DisplayRole).toString();
    // 处理文本内容
    }

    m当前打开词条=text;//历史列表中的项包含了表名

    int index1=text.lastIndexOf(" ");
    int index2=text.lastIndexOf("\t");//ID显示在每一列的最后和tab和空格之间

    QString ID=text.mid(index1+1,index2-index1);
    QString 表名=text.mid(index2+1,text.length()-index2-1);
    QString ini文件=m词典路径+"/tableSet/"+表名+".ini";//更新ini的路径

    QString 结果=表中还原html(ini文件,m词典文件, 表名, ID, &ID);//ID后面不用了, 随意用&ID代替列表词

    p主页Edit->setText(结果);
    //qDebug()<<"七苛有上"<<text;
    //qDebug()<<"七三有且"<<表名<<ID<<ini文件;//注意ID已不是ID值

}





//跟踪光标处的元素
int MW::updateCursorPosition()
{
// 获取当前文本编辑器的光标位置
    QTextCursor cursor = p主页Edit->textCursor();
    QTextDocumentFragment fragment = cursor.selection();


    QTextDocument *doc = p主页Edit->document();
    int 当前行号 = doc->findBlock(cursor.position()).blockNumber();//每一行是以<p>标签来区分的


    QString html = fragment.toHtml();

    int index1= html.indexOf("<a ");
    int index2= html.indexOf("<img ");

   // qDebug() << html;
   ///跳转到db中某相ID的页面.
   if(index1 != -1)
   {
        //cursor.setPosition(0); // 将光标设置在第0个字符的位置
        // 将光标设置在文本编辑器中
        //cursor.clearSelection();
        //p主页Edit->setTextCursor(cursor);//不起取消光标的作用
        //p主页Edit->clearFocus();


        QString 选择字符=去除尖括号并限制长度(html);
        qDebug()<<"选择字符gg"<<选择字符<<选择字符.length();//前面有一段： "\n\np, li { white-space: pre-wrap; }\n\n藻界🔗" ，计算个数要加上，选择了3个字 藻界🔗，实际计算为40。



        qint64 当前记录 = m定时器.elapsed();
        qint64 时间差值=当前记录-m记忆时间;

        if(m任务名=="" &&  时间差值 >2000 && 选择字符.length()<40)//当前没有任务才能跳转, 距离上次跳转的时间距离需大于2秒。选择的字符要小于3个才跳转。
        {
        p主页Edit->clearFocus();//使跳转后的页面不被框选成蓝色。
        m记忆时间 = m定时器.elapsed();//更新记忆时间
        html=html.mid(index1,html.length()-index1);//截去<a 之前的
        index1=html.indexOf(">");
        html=html.mid(0,index1+1);//只留下<a >内的内容


        index1=-1;
        index1=html.indexOf("当前词典");
        if(index1 != -1)//跳转范围是 当前词典
        {
            //例子 <a href="当前词典:新华大字典/4">
            QString 表名,id,ini文件;//为什么不能写成 ini文件
            int index3=html.indexOf(":");
            int index4=html.indexOf("/");
            表名=html.mid(index3+1,index4-index3-1);
 //qDebug() <<"html---"<< html<<表名;
            html=html.mid(index4+1,html.length()-index4);//截去 /号和之前的
            index3=html.indexOf("\"");//找到 " 号
            id=html.mid(0,index3);
 //qDebug() <<"html-++"<< html<<ID;

           //对应的ini文件也要更新
           index4=m词典文件.lastIndexOf("/");
           ini文件=m词典文件.mid(0,index4+1)+"tableSet/"+表名+".ini";

            QString 列表词;
            QString 结果=表中还原html(ini文件,m词典文件, 表名, id, &列表词);
            p主页Edit->setText(结果);
            m更新历史序列(列表词+"\t"+表名);

        }
        }
   }
   if(index2 != -1)
   {
//例子:  前面的一堆字符串 title=\"音频1@D:/QtF/SQLasBOOK/后来.mp3\" width=\"10\" height=\"10\" /><!--EndFragment--></p></body></html>"
        index1=html.indexOf("title=\"");
        html=html.mid(index1+7,html.length()-index1-7);// -7 是减去title=" 之前的

        index1=html.indexOf("@");
        index2=-2;
        index2=html.indexOf("\"");

        QString 类型=html.mid(0,index1-1);
        QString 资源地址=html.mid(index1+1,index2-index1-1);
        qDebug() << "html东走 "<<html;
        qDebug() << "html音频 "<<index1<<index2<<类型<<资源地址;

        if(类型=="音频")
        {
            p音频播放->setMedia(QUrl::fromLocalFile(资源地址));//音频中不能有专辑图，否则无法播放。
            //player->setVolume(50); //0~100音量范围,默认是100
            p音频播放->play();
        }
   }

   else
   {
       qDebug() << "html光标 "<<当前行号<<html;
   }


   return 0;
}


void MW::m插入链接()
{

/**获得db文件中的表**********************************************************************开始**/
    QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
    QSqlDatabase db =QSqlDatabase::addDatabase("QSQLITE");//以“QSQLITE”为数据库类型，在本进程地址空间内创建一个SQLite数据库。

    db.setDatabaseName(m词典文件);              //设置数据库名
    db.open();
     if (!db.open()) {
        qDebug() << "打开数据库失败";
    }

    QStringList 表的名称列表;
    QSqlQuery query(db);
        query.exec("SELECT name FROM sqlite_master WHERE type='table'");//打印出数据库文件中表的名称.
    while (query.next()) {
        QString 表名 = query.value(0).toString();
        qDebug() <<"m插入链接" <<表名;
        if(表名 != "sqlite_sequence")//除了这个表,其它表都加入选项中.
        {   表的名称列表.push_back(表名);}
    }

   // bool ok;
   // m表名= QInputDialog::getItem(this,tr("选择书本"), tr("请选择书本："),表的名称列表,0,false,&ok);

    db.close();                             		//关闭连接
/**获得db文件中的表**********************************************************************结束**/

    // 在你的对话框类的构造函数中
    QWidget *dialog = new QWidget;
    dialog->setWindowTitle("插入链接");
    QVBoxLayout *layout = new QVBoxLayout(dialog);

    QLabel *表们Label= new QLabel("来源",dialog);
    QComboBox *表们= new QComboBox(dialog);
    QLineEdit *ID号 = new  QLineEdit("ID号", dialog);
    QLineEdit *显示文本 = new  QLineEdit("🔗", dialog);//显示文本🔗

    QPushButton *pushButtonOK = new QPushButton("确定新建", dialog);
    QPushButton *pushButtonCancel = new QPushButton("取消", dialog);


    表们->addItems(表的名称列表);

    // 将控件添加到布局中
    layout->addWidget(表们Label);
    layout->addWidget(表们);
    layout->addWidget(ID号);
    layout->addWidget(显示文本);

    layout->addWidget(pushButtonOK);
    layout->addWidget(pushButtonCancel);

   connect(pushButtonOK, &QPushButton::clicked, [=]() {

//例子 "<a href=\"当前词典:新华大字典/4\">这是一条表内链接</a>"
        QString 链接="<a href=\"当前词典:";
        链接+=表们->currentText()+"/";
        链接+=ID号->text()+"\">";
        链接+=显示文本->text()+"</a>";
qDebug() << "要插入的链接 "<<链接;
        QTextCursor cursor = p主页Edit->textCursor();
        // 在光标处插入文本
        cursor.insertHtml(链接);
        // 将光标位置设置为插入文本的位置
        p主页Edit->setTextCursor(cursor);


        dialog->deleteLater();
        delete dialog;

    });

    //取消按键，关闭窗口。
    connect(pushButtonCancel, &QPushButton::clicked, [=]() {
        //qDebug() << "pushButtonCancel!";
        dialog->deleteLater();
        delete dialog;
    });

dialog->show();


}

void MW::m插入音频()
{
       // 在你的对话框类的构造函数中
    QDialog  *dialog = new QDialog ;
    dialog->setWindowTitle("插入音频");
    QGridLayout *layout = new QGridLayout(dialog);


    QPushButton *选择音频件btn= new QPushButton("选择音频", dialog);
    QLineEdit *音频路径LEdit = new  QLineEdit(dialog);

    QLabel *图标高Label= new QLabel("图标高度",dialog);
    QSpinBox *图标高度= new QSpinBox(dialog);
    图标高度->setValue(10);//设置默认高度为10
    图标高度->setMinimum(0); // 设置最小值为 0
    图标高度->setMaximum(10000); // 设置最大值为 1万
    图标高度->setKeyboardTracking(true); // 启用键盘跟踪功能

    QLabel *图标宽Label= new QLabel("图标宽度",dialog);
    QSpinBox *图标宽度= new QSpinBox(dialog);
    图标宽度->setValue(10);//设置默认宽度为10
    图标宽度->setMinimum(0); // 设置最小值为 0
    图标宽度->setMaximum(10000); // 设置最大值为 1万
    图标宽度->setKeyboardTracking(true); // 启用键盘跟踪功能

    QPushButton *自定义图标btn= new QPushButton("自定义图标", dialog);
    QLineEdit *自定义图标LEdit = new  QLineEdit(dialog);
    自定义图标LEdit->setText("默认");

    QCheckBox *复制音频CBox = new QCheckBox("复制音频",dialog);
    QCheckBox *复制图标CBox = new QCheckBox("复制图标",dialog);
    复制音频CBox->setChecked(true);
    复制图标CBox->setChecked(true);

    QPushButton *pushButtonOK = new QPushButton("确定新建", dialog);
    QPushButton *pushButtonCancel = new QPushButton("取消", dialog);



    // 将控件添加到布局中
    layout->addWidget(选择音频件btn,0,0,1,1);//位置 行与列, 占用的行与列
    layout->addWidget(音频路径LEdit,0,1,1,3);

    layout->addWidget(图标高Label,1,0,1,1);
    layout->addWidget(图标高度,1,1,1,1);
    layout->addWidget(图标宽Label,1,2,1,1);
    layout->addWidget(图标宽度,1,3,1,1);

    layout->addWidget(自定义图标btn,2,0,1,1);
    layout->addWidget(自定义图标LEdit,2,1,1,3);

    layout->addWidget(复制音频CBox,3,0,1,1);
    layout->addWidget(复制图标CBox,3,2,1,1);

    layout->addWidget(pushButtonOK,4,1,1,1);
    layout->addWidget(pushButtonCancel,4,2,1,1);


    //选择音频文件
    connect(选择音频件btn, &QPushButton::clicked, [=]() {
        // 创建并显示文件对话框
        if(m词典路径.isEmpty())
        {
            QString filename = QFileDialog::getOpenFileName(this, tr("打开音频文件"),
                                                    QDir::currentPath(),
                                                    tr("音频(*.mp3; *.wav);"));
            音频路径LEdit->setText(filename);
        }
        else//打开了书集，就先从书集中打开文件夹
        {
            QString filename = QFileDialog::getOpenFileName(this, tr("打开音频文件"),
                                                    m词典路径,
                                                    tr("音频(*.mp3; *.wav);"));
            音频路径LEdit->setText(filename);
        }
        dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
        dialog->show();
    });

    //选择自定义图标
    connect(自定义图标btn, &QPushButton::clicked, [=]() {
        // 创建并显示文件对话框
        if(m词典路径.isEmpty())
        {
            QString filename = QFileDialog::getOpenFileName(this, tr("打开图标文件"),
                                                    QDir::currentPath(),
                                                    tr("图片(*.png; *.jpg; *.jpeg; *.icon; *.gif);"));
            自定义图标LEdit->setText(filename);
        }
        else//打开了书集，就先从书集中打开文件夹
        {
            QString filename = QFileDialog::getOpenFileName(this, tr("打开图标文件"),
                                                    m词典路径,
                                                    tr("图片(*.png; *.jpg; *.jpeg; *.icon; *.gif);"));
            自定义图标LEdit->setText(filename);
        }
        dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
        dialog->show();

    });

//插入到QTextEdit, 图片肯定是绝对路径才能显示. 资源可以是绝对也可以是相对. 要用一些标记表示保存时路径是否要截短, 和读出时是否要补充.
//音频0@   图片和资源都要截断, 即复制到工作目录中.
//音频1@   图片截断, 复制到工作目录中. 资源保留原路径.
//音频2@   图片保留原路径. 资源截断, 复制到工作目录中.
//音频3@   图片和资源保留原路径.

//假设image.png和mp3都不在词典的文件中, 执行1@的操作, 就是图片复制到工作文件夹, mp3保持原位置,不复制.  在 QTextEdit的语句如下:
//<img src=\"D:/QtF/SQLasBOOK/词典/photo/image.png\" title=\"音频1@D:/CloudMusic/夏天的风.mp3\" width=\"50\" height=\"20\" />
// 保存在db的语句如下:
//<img src=\"/photo/image.png\" title=\"音频1@D:/CloudMusic/夏天的风.mp3\" width=\"50\" height=\"20\" />

    //确定插入音频
    connect(pushButtonOK, &QPushButton::clicked, [=]() {
        int 复制状态=0;
        if(!复制音频CBox->isChecked())//复制音频没选上
        {    复制状态+=1;     }
        if(!复制图标CBox->isChecked())//复制图标没选上
        {    复制状态+=2;     }
//qDebug() <<"复制状态aa: "<<复制状态;

        QString html语句="<img src=\"";


/**图标文件的选择****************************************************************/
        QString 图标路径=自定义图标LEdit->text();
        if(图标路径 == "默认" || 图标路径.isEmpty())//图标路径是默认或是空, 采用默认的图标
        {
            html语句+=m词典路径+"/photo/audioT.png\" ";

            goto 音频文件的选择;
        }
        if(!自定义图标LEdit->text().isEmpty())//输入框非空
        {

           // 创建QFile对象并检查文件是否存在
            QFile file(图标路径);
            if (file.exists())
            {
               // qDebug() << "文件存在！";
                if(复制状态 == 2 || 复制状态 == 3)//2或3 图标保留在原位置
                {
                    html语句+=图标路径+"\" ";
                    goto 音频文件的选择;
                }
                if(复制状态 == 0 || 复制状态 == 1)//0或1 图标复制到/photo/中 , 默认是复制
                {
                    QString 图标文件名;
                    int index=图标路径.lastIndexOf("/");
                    图标文件名=图标路径.mid(index+1,图标路径.length()-index-1);
                    QString 目标路径=m词典路径+"/photo/"+图标文件名;

                    bool 成功=false;
                    QFile file2(目标路径);

                    index=-1;
                    index=图标路径.indexOf(m词典路径+"/photo");//实现在photo文件夹或其子字夹中就不复制, 实现在photo中分类管理
                    //if(目标路径==图标路径)//证明图标就在 photo 中
                    if(index != -1)
                    {
                        目标路径=图标路径;
                        成功=true;
                        goto 跳过图标复制;
                    }

                    if (file2.exists())//如果目标的目录有同名的文件, 弹窗提示是否要覆盖
                    {
                        switch(QMessageBox::question(this,tr("选择提示框"),//在switch中获得 QMessageBox::question()的返回值
                                                  tr("photo中有同名图片, 是否继续复制？"),
                                                  QMessageBox::Ok|QMessageBox::Cancel,//有Ok和Cancel两个选项
                                                  QMessageBox::Ok))//默认是Ok
                        {
                        case QMessageBox::Ok:
                              成功=文件复制到另一位置(图标路径, 目标路径);
                            break;
                        case QMessageBox::Cancel:
                              dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
                              dialog->show();
                              goto 跳过关闭;
                            break;
                        default:
                            break;
                        }
                    }
                    else//没有同名文件, 直接复制
                    {
                        成功=文件复制到另一位置(图标路径, 目标路径);
                        qDebug() << "文件复制结果"<<成功<<图标路径<<目标路径;
                    }
跳过图标复制:
                    if(成功)
                    {    html语句+=目标路径+"\" ";}
                    else
                    {
                        QMessageBox::information(this,tr("提示"),tr("复制图标失败！"));
                        dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
                        dialog->show();
                        goto 跳过关闭;
                    }
                }
            }
            else
            {
                QMessageBox::information(this,tr("提示"),tr("图标文件不存在！"));
                dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
                dialog->show();
                goto 跳过关闭;
            }
        }


/**音频文件的选择****************************************************************/
音频文件的选择:
        if(!音频路径LEdit->text().isEmpty())//输入框非空
        {
            QString 音频路径 = 音频路径LEdit->text();
           // 创建QFile对象并检查文件是否存在
            QFile file(音频路径);
            if (file.exists())
            {
                qDebug() << "文件存在！";
                if(复制状态 == 1)//1或3 音频保留在原位置
                {
                    html语句+="title=\"音频1@"+音频路径+"\" ";
                    //html语句+="title=\"音频1@"+音频路径+"\" width=\"10\" height=\"10\" />";
                }
                if(复制状态 == 3)//1或3 音频保留在原位置
                {
                    html语句+="title=\"音频3@"+音频路径+"\" ";
                    //html语句+="title=\"音频3@"+音频路径+"\" width=\"10\" height=\"10\" />";
                }

                if(复制状态 == 0 || 复制状态 == 2)//0或2 要复制音频到 audio
                {
                    QString 音频文件名;
                    int index=音频路径.lastIndexOf("/");
                    音频文件名=音频路径.mid(index+1,音频路径.length()-index-1);
                    QString 目标路径=m词典路径+"/audio/"+音频文件名;

                    bool 成功=false;
                    QFile file2(目标路径);

                    index=-1;
                    index=音频路径.indexOf(m词典路径+"/audio");//实现在audio文件夹或其子字夹中就不复制, 实现在audio中分类管理
                    //if(目标路径==音频路径)//证明音频就在 audio 中
                    if(index != -1)
                    {
                        目标路径=音频路径;
                        成功=true;
                        goto 跳过音频复制;
                    }


                    if (file2.exists())//如果目标的目录有同名的文件, 弹窗提示是否要覆盖
                    {                        
                        switch(QMessageBox::question(this,tr("选择提示框"),//在switch中获得 QMessageBox::question()的返回值
                                                  tr("audio中有同名音频, 是否继续复制？"),
                                                  QMessageBox::Ok|QMessageBox::Cancel,//有Ok和Cancel两个选项
                                                  QMessageBox::Ok))//默认是Ok
                        {
                        case QMessageBox::Ok:
                              成功=文件复制到另一位置(音频路径, 目标路径);
                            break;
                        case QMessageBox::Cancel:
                              dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
                              dialog->show();
                              goto 跳过关闭;
                            break;
                        default:
                            break;
                        }
                    }
                    else//没有同名文件, 直接复制
                    {
                        成功=文件复制到另一位置(音频路径, 目标路径);
                        qDebug() << "文件复制结果"<<成功<<音频路径<<目标路径;
                    }
跳过音频复制:
                    if(成功)//复制文件成功
                    {
                        if(复制状态 == 0){   html语句+="title=\"音频0@"+目标路径+"\" "; }
                        if(复制状态 == 2){   html语句+="title=\"音频2@"+目标路径+"\" "; }
                    }
                    else
                    {
                        QMessageBox::information(this,tr("提示"),tr("复制音频失败！"));
                        dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
                        dialog->show();
                        goto 跳过关闭;
                    }

                }

            }
            else
            {
                QMessageBox::information(this,tr("提示"),tr("音频文件不存在！"));
                dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
                dialog->show();
                goto 跳过关闭;
            }

            QString 图标高 = 图标高度->text();
            QString 图标宽 = 图标宽度->text();

            html语句+="width=\""+图标宽+"\" height=\""+图标高+"\" />";
            qDebug()<<"img jj"<<html语句;

            QTextCursor cursor = p主页Edit->textCursor();
            // 在光标处插入文本
            cursor.insertHtml(html语句);
           // 将光标位置设置为插入文本的位置
            p主页Edit->setTextCursor(cursor);
        }
        else
        {
            QMessageBox::information(this,tr("提示"),tr("请选择音频文件！"));
            dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
            dialog->show();
            goto 跳过关闭;
        }


        ///按确定按键, 仅在成功插入才会自动删除对话框.
        dialog->deleteLater();
        delete dialog;
跳过关闭:
    //未完成文件的选择,不能删除对话框.
    qDebug() << "关闭对话框再到这, 表明选择了正常的图标和音频. 没关对话框到这, 表明没选择成功！";

    });

    //取消按键，关闭窗口。
    connect(pushButtonCancel, &QPushButton::clicked, [=]() {
        dialog->deleteLater();
        delete dialog;
    });


    //dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
    dialog->show();



}


void MW::m插入图片()
{
      // 在你的对话框类的构造函数中
    QDialog  *dialog = new QDialog ;
    dialog->setWindowTitle("插入图片");
    QGridLayout *layout = new QGridLayout(dialog);

    QLabel *图标高Label= new QLabel("图标高度",dialog);
    QSpinBox *图标高度= new QSpinBox(dialog);
    图标高度->setMinimum(0); // 设置最小值为 0
    图标高度->setMaximum(10000); // 设置最大值为 1万
    图标高度->setKeyboardTracking(true); // 启用键盘跟踪功能

    QLabel *图标宽Label= new QLabel("图标宽度",dialog);
    QSpinBox *图标宽度= new QSpinBox(dialog);
    图标宽度->setMinimum(0); // 设置最小值为 0
    图标宽度->setMaximum(10000); // 设置最大值为 1万
    图标宽度->setKeyboardTracking(true); // 启用键盘跟踪功能

    QPushButton *自定义图标btn= new QPushButton("选择图片", dialog);
    QLineEdit *自定义图标LEdit = new  QLineEdit(dialog);

    QCheckBox *复制图标CBox = new QCheckBox("复制图片",dialog);
    复制图标CBox->setChecked(true);

    QPushButton *pushButtonOK = new QPushButton("确定插入", dialog);
    QPushButton *pushButtonCancel = new QPushButton("取消", dialog);

    // 将控件添加到布局中
    layout->addWidget(自定义图标btn,0,0,1,1);
    layout->addWidget(自定义图标LEdit,0,1,1,3);

    layout->addWidget(图标高Label,1,0,1,1);
    layout->addWidget(图标高度,1,1,1,1);
    layout->addWidget(图标宽Label,1,2,1,1);
    layout->addWidget(图标宽度,1,3,1,1);

    layout->addWidget(复制图标CBox,2,0,1,1);

    layout->addWidget(pushButtonOK,3,1,1,1);
    layout->addWidget(pushButtonCancel,3,2,1,1);

    //选择图片
    connect(自定义图标btn, &QPushButton::clicked, [=]() {
        // 创建并显示文件对话框
        if(m词典路径.isEmpty())
        {
            QString filename = QFileDialog::getOpenFileName(this, tr("打开图像文件"),
                                                    QDir::currentPath(),
                                                    tr("图片(*.png; *.jpg; *.jpeg; *.icon; *.gif);"));
            自定义图标LEdit->setText(filename);
        }
        else//打开了书集，就先从书集中打开文件夹
        {
            QString filename = QFileDialog::getOpenFileName(this, tr("打开图像文件"),
                                                    m词典路径,
                                                    tr("图片(*.png; *.jpg; *.jpeg; *.icon; *.gif);"));
            自定义图标LEdit->setText(filename);
        }
        dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
        dialog->show();

    });

    //确定插入图片
    connect(pushButtonOK, &QPushButton::clicked, [=]() {

        QString html语句="<img src=\"";

/**图标文件的选择****************************************************************/
        QString 图标路径=自定义图标LEdit->text();
        if(图标路径.isEmpty())//图标路径是默认或是空,
        {
            QMessageBox::information(this,tr("提示"),tr("请选择图片！"));
            dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
            dialog->show();
        }
        if(!自定义图标LEdit->text().isEmpty())//输入框非空
        {

           // 创建QFile对象并检查文件是否存在
            QFile file(图标路径);
            if (file.exists())
            {
               // qDebug() << "文件存在！";
                if(!复制图标CBox->isChecked())//未选复制 图片保留在原位置
                {
                    html语句+=图标路径+"\" ";
                }
                else//图标复制到/photo/中  默认是复制
                {
                    QString 图标文件名;
                    int index=图标路径.lastIndexOf("/");
                    图标文件名=图标路径.mid(index+1,图标路径.length()-index-1);
                    QString 目标路径=m词典路径+"/photo/"+图标文件名;

                    bool 成功=false;
                    QFile file2(目标路径);

                    index=-1;
                    index=图标路径.indexOf(m词典路径+"/photo");//实现在photo文件夹或其子字夹中就不复制, 实现在photo中分类管理
                    //if(目标路径==图标路径)//证明图标就在 photo 中
                    if(index != -1)
                    {
                        目标路径=图标路径;
                        成功=true;
                        goto 跳过图标复制;
                    }

                    if (file2.exists())//如果目标的目录有同名的文件, 弹窗提示是否要覆盖
                    {
                        switch(QMessageBox::question(this,tr("选择提示框"),//在switch中获得 QMessageBox::question()的返回值
                                                  tr("photo中有同名图片, 是否继续复制？"),
                                                  QMessageBox::Ok|QMessageBox::Cancel,//有Ok和Cancel两个选项
                                                  QMessageBox::Ok))//默认是Ok
                        {
                        case QMessageBox::Ok:
                             成功=文件复制到另一位置(图标路径, 目标路径);
                             break;
                        case QMessageBox::Cancel:
                             dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
                             dialog->show();
                             goto 跳过关闭;
                             break;
                        default:
                             break;
                        }
                    }
                    else//没有同名文件, 直接复制
                    {
                        成功=文件复制到另一位置(图标路径, 目标路径);
                        qDebug() << "文件复制结果"<<成功<<图标路径<<目标路径;
                    }
跳过图标复制:
                    if(成功)
                    {
                        html语句+=目标路径+"\" title=\"图片1@\" ";//资源类型是图片， 1@代表截取图片前面的绝对路径。
                    }
                    else
                    {
                        QMessageBox::information(this,tr("提示"),tr("复制图片失败！"));
                        dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
                        dialog->show();
                        goto 跳过关闭;
                    }
                }
            }
            else
            {
                QMessageBox::information(this,tr("提示"),tr("图片文件不存在！"));
                dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
                dialog->show();
                goto 跳过关闭;
            }

            QString 图标高 = 图标高度->text();
            QString 图标宽 = 图标宽度->text();

            if(图标高 != "0"  && 图标宽 != "0")
            {
                html语句+="width=\""+图标宽+"\" height=\""+图标高+"\" />";
            }
            else
            {
                html语句+=" />";
            }
            qDebug()<<"img eee"<<html语句;

            QTextCursor cursor = p主页Edit->textCursor();
            // 在光标处插入文本
            cursor.insertHtml(html语句);
           // 将光标位置设置为插入文本的位置
            p主页Edit->setTextCursor(cursor);

        }
        ///按确定按键, 仅在成功插入才会自动删除对话框.
        dialog->deleteLater();
        delete dialog;
跳过关闭:
    //未完成文件的选择,不能删除对话框.
    qDebug() << "关闭对话框再到这, 表明选择了正常的图片. 没关对话框到这, 表明没选择成功！";

    });


     //取消按键，关闭窗口。
    connect(pushButtonCancel, &QPushButton::clicked, [=]() {
        dialog->deleteLater();
        delete dialog;
    });


    //dialog->hide();//要先隐藏再显示,不然对话框跑到背后去了.
    dialog->show();

}

void MW::m选择书本()
{

    int index= -2;
    index=m词典文件.indexOf(".db");
    if(index != -1)
    {

    QString Path(m词典文件);
    //setWindowTitle(Path);
//qDebug() <<"数据库路径 "<<m词典文件;

    QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
    QSqlDatabase db =QSqlDatabase::addDatabase("QSQLITE");//以“QSQLITE”为数据库类型，在本进程地址空间内创建一个SQLite数据库。

    db.setDatabaseName(Path);              //设置数据库名
    db.open();
     if (!db.open()) {
        qDebug() << "打开数据库失败";
    }

    QStringList 表的名称列表;
    QSqlQuery query(db);


    query.exec("SELECT name FROM sqlite_master WHERE type='table'");//打印出数据库文件中表的名称.
    while (query.next()) {
        QString 表名 = query.value(0).toString();
        qDebug() << 表名;
        if(表名 != "sqlite_sequence")//除了这个表,其它表都加入选项中.
        {   表的名称列表.push_back(表名);}
    }

    bool ok;
    m表名= QInputDialog::getItem(this,tr("选择书本"), tr("请选择书本："),表的名称列表,0,false,&ok);

    int index =m词典文件.lastIndexOf("/");
        m词典路径=m词典文件.mid(0,index);//得到词典的路径
        mINI文件=m词典路径+"/tableSet/"+m表名+".ini";//更新ini的路径
    m词条模板文件=m词典路径+"/tableSet/"+m表名+".rtf";//更新模板rtf的路径
qDebug() <<"数据库路径gadsg "<<m词典文件<<mINI文件<<m词条模板文件;

    setWindowTitle(m词典文件+"  "+m表名);


    db.close();                             		//关闭连接
    m更新词典序列();
    }
    else//如果db文件没有打开过
    {
        QMessageBox::information(nullptr, "提示", "需要先打开db文件！");
    }


}

void MW::m修改词条()
{
    qDebug()<<"当前词条是啥 "<<m当前打开词条;
    if(m当前打开词条.length()>2)
    {
        QString SQL语句="DELETE FROM "; //  表名  WHERE ID = id;  //id 数字不加单引号

        int index1=m当前打开词条.lastIndexOf(" ");
        int index2=m当前打开词条.lastIndexOf("\t");//ID显示在每一列的最后和tab和空格之间

        QString ID=m当前打开词条.mid(index1+1,index2-index1-1);
        QString 表名=m当前打开词条.mid(index2+1,m当前打开词条.length()-index2-1);
        QString ini文件=m词典路径+"/tableSet/"+表名+".ini";

        QStringList ini第三行= ini读尖括号格式(ini文件, "<^>");//表的类型是词典还是笔记
        if(ini第三行.length()>0)//必须有元素才比较是笔记还是词典, 否则查[0]时数组越界.
        {
            if(ini第三行[0]=="笔记")
            {
                p主页Edit->clear();
                p主页Edit->setText(表中还原html(ini文件, m词典文件,表名, ID, &ID));//当前词条
                m任务名="修改笔记词条";//后续由函数 m任务提交 完成.
            }
            if(ini第三行[0]=="词典")
            {
                p主页Edit->clear();
                p主页Edit->setText(词典词条像模板还原(ini文件, m词典文件,表名, ID));//当前词条
                m任务名="修改词典词条";//后续由函数 m任务提交 完成.


            }
        }


    }

//词典词条像模板还原(QString ini文件, QString db文件, QString 表名, QString ID);


}


void MW::m删除词条()
{
    qDebug()<<"删除当前词条是啥 "<<m当前打开词条;
    if(m当前打开词条.length()>2)
    {
        QString SQL语句="DELETE FROM "; //  表名  WHERE ID = id;  //id 数字不加单引号

        int index1=m当前打开词条.lastIndexOf(" ");
        int index2=m当前打开词条.lastIndexOf("\t");//ID显示在每一列的最后和tab和空格之间

        QString ID=m当前打开词条.mid(index1+1,index2-index1);
        QString 表名=m当前打开词条.mid(index2+1,m当前打开词条.length()-index2-1);

        SQL语句+=表名+" WHERE ID =" +ID+ ";";
        sql写操作(m词典文件, SQL语句);

        m更新词典序列();
    }


}


void MW::m删除书本()
{
    qDebug()<<"删除当前书本是啥 "<<m当前打开词条;
    if(m表名.length()>0)
    {
        switch(QMessageBox::question(this,tr("删除提示框"),//在switch中获得 QMessageBox::question()的返回值
                                     tr("是否删除书本 ")+m表名+" ?",
                                     QMessageBox::Ok|QMessageBox::Cancel,//有Ok和Cancel两个选项
                                     QMessageBox::Ok))//默认是Ok
        {
        case QMessageBox::Ok:
        {
            QString SQL语句="DROP TABLE "; //  后面加 表名 结尾不用加分号;
            SQL语句+=m表名;
            sql写操作(m词典文件, SQL语句);
            m更新词典序列();

            //删除模板和ini文件
            QString ini文件=m词典路径+"/tableSet/"+m表名+".ini";
            QString rtf文件=m词典路径+"/tableSet/"+m表名+".rtf";
            if(QFile::remove(ini文件))
            {   qDebug() << "删除了 "+ini文件;  }
            else
            {   qDebug() << "删除 "+ini文件 +" 失败!!";  }

            if(QFile::remove(rtf文件))
            {   qDebug() << "删除了 "+rtf文件;  }
            else
            {   qDebug() << "删除 "+rtf文件 +" 失败!!";  }

        }
            break;
        case QMessageBox::Cancel:
            break;
        default:
            break;
        }

    }

}


void MW::m插入表格()
{
      // 在你的对话框类的构造函数中
    QDialog  *dialog = new QDialog ;
    dialog->setWindowTitle("插入表格");
    QGridLayout *layout = new QGridLayout(dialog);

    QLabel *行数Label= new QLabel("行数",dialog);
    QSpinBox *行数= new QSpinBox(dialog);
    行数->setValue(3);//设置默认3行
    行数->setMinimum(1); // 设置最小值为 1
    行数->setMaximum(10000); // 设置最大值为 1万
    行数->setKeyboardTracking(true); // 启用键盘跟踪功能

    QLabel *列数Label= new QLabel("列数",dialog);
    QSpinBox *列数= new QSpinBox(dialog);
    列数->setValue(4);//设置默认4列
    列数->setMinimum(1); // 设置最小值为 1
    列数->setMaximum(10000); // 设置最大值为 1万
    列数->setKeyboardTracking(true); // 启用键盘跟踪功能


    QPushButton *pushButtonOK = new QPushButton("确定插入", dialog);
    QPushButton *pushButtonCancel = new QPushButton("取消", dialog);

    // 将控件添加到布局中
    layout->addWidget(行数Label,0,0,1,1);
    layout->addWidget(行数,0,1,1,1);
    layout->addWidget(列数Label,0,2,1,1);
    layout->addWidget(列数,0,3,1,1);

    layout->addWidget(pushButtonOK,1,1,1,1);
    layout->addWidget(pushButtonCancel,1,3,1,1);

    dialog->show();



    connect(pushButtonOK, &QPushButton::clicked, [=]() {

    QString html表格="<table border=\"1\"; cellspacing=\"0\"; bordercolor=\"#99ccff\">";

        for(int i=0; i<行数->value(); i++ )
        {
            html表格+="<tr>";
            for(int j=0; j<列数->value(); j++)
            {
                if(i==0)
                {
                    html表格+="<td>一</td>";//第一行插入个 "一", 用来保持宽度
                }
                else
                {  html表格+="<td></td>";}

            }
            html表格+="</tr>";
        }
        html表格+="</table>";

        QTextCursor cursor = p主页Edit->textCursor();
        //QTextDocumentFragment fragment = cursor.selection();

        QTextDocument *doc = p主页Edit->document();
        int 光标台前行 = doc->findBlock(cursor.position()).blockNumber();//每一行是以<p>标签来区分的
        // 按行分割文本
        QStringList html字符列表 = p主页Edit->toHtml().split("\n");
        int 表开始=0, 表结束=0, 行=0, 列=0;

        int 光标台后行=找表位置(html字符列表, 光标台前行, &表开始, &表结束,&行,&列);

         if(光标台后行== -1)//问题: 暂时不允许表格中插入表格, 因为后面处理大麻烦.
         {
            // 在光标处插入文本
             cursor.insertHtml(html表格);
            // 将光标位置设置为插入文本的位置
            p主页Edit->setTextCursor(cursor);
         }
            dialog->deleteLater();
            delete dialog;
    });
    //取消按键，关闭窗口。
    connect(pushButtonCancel, &QPushButton::clicked, [=]() {
        dialog->deleteLater();
        delete dialog;
    });

}

void MW::m表格操作(QString 操作类型)
{
    QTextCursor cursor = p主页Edit->textCursor();
    //QTextDocumentFragment fragment = cursor.selection();

    QTextDocument *doc = p主页Edit->document();
    int 光标台前行 = doc->findBlock(cursor.position()).blockNumber();//每一行是以<p>标签来区分的

    // 按行分割文本
    QStringList html字符列表 = p主页Edit->toHtml().split("\n");
    int 表开始=0, 表结束=0, 行=0, 列=0;

    int 光标台后行=找表位置(html字符列表, 光标台前行, &表开始, &表结束,&行,&列);

    qDebug()<<"增加一行asa"<<光标台前行<<光标台后行<<表开始<<表结束<<行<<列;

    if(光标台后行 != -1 && 表开始<表结束 && 表开始>0)
    {
        QStringList html字符列表前;
        QStringList html表格区域;
        QStringList html字符列表后;

        for(int i=0; i<表开始; i++)
        {    html字符列表前.append(html字符列表[i]);}

        for(int i=表开始; i<表结束+1; i++)
        {    html表格区域.append(html字符列表[i]);}


        if(html字符列表.length()>=表结束+1)
        {
          for(int i=表结束+1; i<html字符列表.length(); i++)
          {    html字符列表后.append(html字符列表[i]);  }
        }

        html表格区域=规范化表格(html表格区域);

//        for(int i=0; i < html字符列表后.length(); i++)
//        {
//            qDebug()<<"html字符列表后gg"<<html字符列表后[i];
//        }

        html表格区域=表格操作(html表格区域, 操作类型,行,列);

        for(int i=0; i < html表格区域.length(); i++)
        {
            qDebug()<<"html字符列表后gg"<<html表格区域[i];
        }

        //拼接要修改后的表格
        QString html文本;
        for(int i=0; i<html字符列表前.length();i++)
        {
            html文本+=html字符列表前[i]+"\n";
        }
        for(int i=0; i<html表格区域.length();i++)
        {
            html文本+=html表格区域[i]+"\n";
        }
        for(int i=0; i<html字符列表后.length();i++)
        {
            html文本+=html字符列表后[i]+"\n";
        }

        m表格操作保存文档=p主页Edit->toHtml();//获得修改表格之前的文本, 为了能有撤消一步的功能.
        //p主页Edit->setHtml(html文本);
        p主页Edit->setText(html文本);

    }


}



void MW::m表格增加一行()
{
    m表格操作("增加一行");
}

void MW::m表格增加一列()
{
    m表格操作("增加一列");
}

void MW::m表格删除当前行()
{
    m表格操作("删除当前行");
}

void MW::m表格删除当前列()
{
    m表格操作("删除当前列");
}

void MW::m表格返回上一步()
{

    //m表格操作保存文档 的内容只有在表格操作时才加入内容, 这函数用完就清空.
    if(!m表格操作保存文档.isEmpty())
    {
        switch(QMessageBox::question(this,tr("返回上一步"),//在switch中获得 QMessageBox::question()的返回值
                                     tr("文档将会返回到上次操作表格前的状态, 是否继续？"),
                                     QMessageBox::Ok|QMessageBox::Cancel,//有Ok和Cancel两个选项
                                     QMessageBox::Ok))//默认是Ok
        {
        case QMessageBox::Ok:
             p主页Edit->setText(m表格操作保存文档);
             m表格操作保存文档.clear();
             break;
        case QMessageBox::Cancel:
             break;
        default:
             break;
        }
    }
    else
    {
        QMessageBox::information(nullptr, "提示", "没有能返回的表格操作！");
    }

}
